package main

import (
	"bufio"
	"encoding/json"
	"log"
	"os"
	"strconv"
	"strings"
	"sync/atomic"
	"time"

	"gitee.com/fcsvr/fc/fclog"
	"github.com/go-resty/resty/v2"
	"github.com/tidwall/gjson"
)

func SimulateSuper() {
	simulateData := SimulateSuperData{
		Type: "SUPER",
		Settings: SuperSetting{
			InstrumentType:    "EQUITY",
			Region:            "USA",
			Universe:          "TOP3000",
			Delay:             1,
			Decay:             5,
			Neutralization:    "INDUSTRY",
			Truncation:        0.01,
			Pasteurization:    "ON",
			UnitHandling:      "VERIFY",
			NanHandling:       "OFF",
			MaxTrade:          "ON",
			Language:          "FASTEXPR",
			Visualization:     false,
			SelectionHandling: "POSITIVE",
			SelectionLimit:    10,
		},
		Selection: "",
		Combo:     "",
	}

	//for G_SaCount < G_AlphaLen-1 {
	for G_Count < G_AlphaLen-1 {
		count := atomic.AddInt32(&G_Count, 1)
		simulateData.Selection = G_SimulateSuperData[count].Selection
		simulateData.Combo = G_SimulateSuperData[count].Combo
		fclog.Info("Index: %d, %s", count, simulateData.Selection)
		simulateData.Settings.Neutralization = G_SimulateSuperData[count].Settings.Neutralization
		simulateData.Settings.Region = G_SimulateSuperData[count].Settings.Region
		simulateData.Settings.Universe = G_SimulateSuperData[count].Settings.Universe
		simulateData.Settings.SelectionLimit = G_SimulateSuperData[count].Settings.SelectionLimit
		simulateData.Settings.SelectionHandling = G_SimulateSuperData[count].Settings.SelectionHandling
		simulateJson, _ := json.Marshal(simulateData)

		retry_num := G_RetryNum
		simProgressUrl := ""
		var resp *resty.Response

		for retry_num > 0 {
			resp, _ = G_Client.R().SetHeader("Content-Type", "application/json").SetBody(simulateJson).Post("https://api.worldquantbrain.com/simulations")
			//fmt.Println("header: ", resp.Header())
			//fmt.Println("body: ", string(resp.Body()))
			header, exists := resp.Header()["Location"]
			if exists {
				simProgressUrl = header[0]

				for {
					resp, _ = G_Client.R().SetHeader("Content-Type", "application/json").Get(simProgressUrl)
					if _, exists := resp.Header()["Retry-After"]; !exists {
						break
					}
					time.Sleep(time.Second * 2)
				}

				strBody := string(resp.Body())
				alphaID := gjson.Get(strBody, "alpha").String()

				if alphaID == "" {
					fclog.Warn("Simulate Index = %d, AlphaID = Null, Body = %v, code = %v", count, resp.String(), resp.StatusCode())
					//time.Sleep(time.Minute)
				} else {
					fclog.Info("Simulate Index = %d, AlphaID = %s, go to Check", count, alphaID)
					//go CheckAlpha(int(count), alphaID)
				}

				break
			} else {
				fclog.Info("Simulate Index: %d, No Location, Response Status Code: %v,%v, Retry_num = %d", count, resp.StatusCode(), resp.String(), retry_num)
			}
			if resp.StatusCode() == int(429) {
				time.Sleep(time.Minute * time.Duration(G_RetryNum-retry_num+1))
			} else if resp.StatusCode() == int(401) {
				G_Client.R().SetBasicAuth(G_User, G_Pswd).Post("https://api.worldquantbrain.com/authentication")
				time.Sleep(time.Second * 5)
			} else {
				fclog.Error("Simulate Index: %d, Response Status Code: %v, %v", count, resp.StatusCode(), resp.String())
				time.Sleep(time.Minute)
			}
			retry_num -= 1
			if retry_num == 0 {
				fclog.Error("Simulate Index: %d, Retry num: %d,  Response Status Code: %v, %v", count, retry_num, resp.StatusCode(), resp.String())
			}
		}

	}
	G_WaitGroup.Done()
}

func SimulateSuperPool() {
	for i := 0; i < G_Conf.SimulateNum; i++ {
		G_WaitGroup.Add(1)
		go SimulateSuper()
		//go Test()
	}
	G_WaitGroup.Wait()
}

func ConstructSuperFromFile(filepath string) {
	file, err := os.Open(filepath)
	if err != nil {
		log.Println(err)
		return
	}
	defer file.Close()

	simulateSuperDate := SimulateSuperData{}
	scanner := bufio.NewScanner(file)
	scanner.Split(bufio.ScanLines)
	for scanner.Scan() {
		line := scanner.Text()
		line = strings.ReplaceAll(line, " ", "")
		parts := strings.Split(line, G_Split)
		//fclog.Debug("line = %s", line)
		//fclog.Debug("parts = %v, %v, %v", parts[1], parts[2], parts[3])
		simulateSuperDate.Settings.Region = parts[1]
		simulateSuperDate.Selection = parts[2]
		simulateSuperDate.Combo = parts[3]
		simulateSuperDate.Settings.SelectionLimit, _ = strconv.Atoi(parts[4])
		//fclog.Debug("decay = %d", decay)
		simulateSuperDate.Settings.SelectionHandling = parts[5]
		simulateSuperDate.Settings.Universe = parts[6]
		simulateSuperDate.Settings.Neutralization = parts[7]
		G_SimulateSuperData = append(G_SimulateSuperData, simulateSuperDate)
	}
	G_AlphaLen = int32(len(G_SimulateSuperData))
	fclog.Debug("ConstructSuperFromFile super len = %d", len(G_SimulateSuperData))
}
